Verlet integration
$ \ddot\bm x=\bm F(\bm x)
$ \bm x_i:=\bm x(t_i)
$ \bm v_i:=\dot\bm x(t_i)
$ t_i:=t_0+i⊿t
導出してみる
単位質量あたりの運動方程式は$ \ddot\bm x=\bm F(\bm x)
$ \left(\frac{⊿^2\bm x}{{⊿t}^2}\right)_i=\frac{\left(\frac{⊿\bm x}{⊿t}\right)_{i+1}-\left(\frac{⊿\bm x}{⊿t}\right)_i}{⊿t_i}
$ =\frac{\bm x_{i+2}}{⊿t_{i+1}⊿t_i}-\frac{\bm x_{i+1}}{⊿t_{i+1}⊿t_i}+\frac{\bm x_{i+1}}{⊿t_i⊿t_i}-\frac{\bm x_{i}}{⊿t_i⊿t_i}
$ =\frac{\bm x_{i+2}-2\bm x_{i+1}+\bm x_i}{{⊿t}^2}
$ \because⊿t_i=t_{i+1}-t_i=(i+1)⊿t-i⊿t=⊿t
$ \therefore \bm x_{i+2}=2\bm x_{i+1}-\bm x_i+\bm F(\bm x_i){⊿t}^2
これは$ \bm x_{i+2}=\bm x_{i+1}+\bm v_i⊿t+\bm F(\bm x_i){⊿t}^2とも表せる
初期値は$ \bm x_1=\bm x_0+\bm v_0⊿t+\frac12\bm F(\bm x_0)⊿t^2とする
根拠は?takker.icon
まあTaylor展開とかからの類推で、$ \frac12をつけるのは違和感ないけど $ \bm x(t+⊿t)=\bm x(t)+\dot\bm x(t)⊿t+\frac12\ddot\bm x(t)⊿t^2+\frac16\bm x'''(t)⊿t^3+\Omicron(⊿t^4)
$ \bm x(t-⊿t)=\bm x(t)-\dot\bm x(t)⊿t+\frac12\ddot\bm x(t)⊿t^2-\frac16\bm x'''(t)⊿t^3+\Omicron(⊿t^4)
$ \therefore \bm x_{i+1}+\bm x_{i-1}=2\bm x_i+\ddot\bm x_i⊿t^2+\Omicron(⊿t^4)
$ =2\bm x_i+\bm F(\bm x_i)⊿t^2+\Omicron(⊿t^4)
3次のオーダーまで計算している点に注目takker.icon
テイラー展開を元にするなら、$ \bm Fは中間の$ \bm xを使うのが妥当なのかな
$ ⊿t^4の項まで考慮したらどうなるんだろう
$ \bm F''(\bm x_i)を解く必要がでてくるtakker.icon
$ \bm x''''_i=\bm F''(\bm x_i)
上の展開と近似と同じことをすれば、$ ⊿t^3オーダーまでの近似式が求まる
$ \bm F(\bm x_{i+1})+\bm F(\bm x_{i-1})=2\bm F(\bm x_i)+\ddot\bm F(\bm x_i)⊿t^2+\Omicron(⊿t^4)ー①
$ ⊿t^4で打ち切った運動方程式は
$ \bm x_{i+1}+\bm x_{i-1}=2\bm x_i+\ddot\bm x_i⊿t^2+\frac1{12}\bm x''''_i⊿t^4+\Omicron(⊿t^5)ー②
以上より
$ \bm x_{i+1}+\bm x_{i-1}=2\bm x_i+\bm F(\bm x_i)⊿t^2+\frac1{12}(\bm F(\bm x_{i+1})+\bm F(\bm x_{i-1})-2\bm F(\bm x_i))⊿t^2
いや、この式は不合理だ
①は3次で打ち切っているのに、②は4次で打ち切っている
4次の項を入れたとしても、①で4次を無視しているので、②の4次の項を考慮する意味がなくなる
3次で打ち切る近似法以外に手立てはなさそうだ
運動方程式を差分化した差分方程式を逐次計算しているだけだった
相互作用を後から計算している
前進差分で考えるなら$ \bm x_iの値を使いたい 先に$ \bm x_iで総合作用を計算して、運動方程式を逐次計算する際に使えばいい
こんな感じかな
code:ts
interface Point { x: number; y: number; };
declare const points: { next: Point; now: Point; }[];
declare const internalForces;
const dt = 0.05;
const forces = [];
// x_{i+1} から相互作用 F(x_{i+1}) を計算
for (const { from, to, calc } of internalForces) {
const force = calc(pointsfrom.next, pointsto.next); forcesto = add(forcesto, force); }
// 新しい x_{i+2}, x_{i+1} を求める
for (let i = 0; i < points.length; i++) {
const next = pointsi.next; pointsi.next = add(add(next, sub(next, pointsi.now)), forcesi * dt ** 2); }
利点はなに?takker.icon
速度を明示的に求めなくていいということだけっぽい?
数値計算の経験があまりないせいかもだけど、ありがたみがよくわからない 桁落ちをベルレ法より抑えられると書いてあるが、根拠が不明takker.icon
どちらも$ ⊿t^3の項がある
布のsimulation
ドラッグする点をマウス座標と一致させればいい
どれをドラッグの対象にするかは、各点とカーソルとの距離の近さで決める
具体的なコードサンプル
こっちのほうがまとまってるかも
野中サンプルはリンク切れ
kyndサンプルはCodePenで見れる
既存のJS実装
engineとして提供
1番star多い
開発も継続してる
作者の解説